/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package consumo;

import co.gov.minagricultura.*;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Iterator;
import java.util.List;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import javax.xml.bind.*;
import org.eclipse.persistence.internal.jpa.EntityManagerImpl;
import wsDANE.SipsaPromediosMayoristasParcial;

/**
 *
 * @author leonardo.bravo
 */
public class Consumo {

    /**
     * @param args the command line arguments
     */
    private static final String PRECIOSDIARIOS_XML = "c:/bases/PRECIOSDIARIOS.xml";

    public static void main(String[] args) throws JAXBException, IOException {

        JAXBContext context = JAXBContext.newInstance(
                wsDANE.SipsaPromediosMayoristasParcial.class);

        //persistXML(context);
        Consumo consumo = new Consumo();
        consumo.persistDatabaseSipsaDiarioConDescripcion();
        //persistDatabaseSipsaDiario();
        //Unmarshaller um = context.createUnmarshaller();
    }

    private static void persistXML(JAXBContext context) throws JAXBException, PropertyException {
        Marshaller m = context.createMarshaller();
        m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);

        java.util.List<wsDANE.SipsaPromediosMayoristasParcial> pspr = Consumo.promediosSipsaParcial();
        // Write to System.out
        // this has to be an xml list objects.
        m.marshal(pspr, System.out);

        // Write to File
        m.marshal(pspr, new File(PRECIOSDIARIOS_XML));
    }

    public  long getUltimoConsecutivoEnBaseSipsa(EntityManagerImpl entityManager) {
        Long idConsecutivoUltimo = (Long) entityManager.createNamedQuery("SipsaDiarioConDescripcionesCambios.findMaxConsecutivo").getSingleResult();
        return idConsecutivoUltimo.longValue();
    }

    /*
    * @author leonardo.bravo  
    * Inserta datos en clases mapeadas SipsaDiario y  sipsaDiarioConDescripcion. 
    * Define y usa una instancia de la implementacón del entity manager, asigna valores a las clases mapeadas 
    * y persiste según la existencia en la tabla destino de todos los registros reportados en una lista de
    * precios mayoristas reportados por el webservice del dane.  
    */
    
    private  void persistDatabaseSipsaDiarioConDescripcion() {

        EntityManagerFactory entityManagerFactory;
        entityManagerFactory = Persistence.createEntityManagerFactory("ConsumoPU", new java.util.HashMap());
        EntityManagerImpl entityManager; 

        List<wsDANE.SipsaPromediosMayoristasParcial> arrayPromediosSipsa = promediosSipsaParcial();
        System.out.println(" Cantidad de Datos enviados por Dane: " + arrayPromediosSipsa.size());
       
        entityManager= (EntityManagerImpl) entityManagerFactory.createEntityManager();
        //long nuevoConsecutivo = getUltimoConsecutivoEnBaseSipsa(entityManager);
        
        EntityTransaction trx  = entityManager.getTransaction();
        
        
        for (wsDANE.SipsaPromediosMayoristasParcial sipsaPromedioMayorista : arrayPromediosSipsa) {

            if (!entityManager.getTransaction().isActive()) {
                trx = entityManager.getTransaction();
                       trx.begin();
            }
            
            SipsaDiarioPK sipsaDiarioPK = new SipsaDiarioPK();
            SipsaDiarioPK sipsaDiarioPKSemanaAnterior = null;
            try {
                //Obtiene codigo_producto
                List  listaCodigoProducto =  entityManager.createNamedQuery(
                        "SipsaProductosDiarios.findCodProductoByNombreProductoDiarios").setParameter(
                        "nombreProductoProductosDiarios", sipsaPromedioMayorista.getArtiNombre()).getResultList();
                Long codigo_producto;
                if (listaCodigoProducto !=null && !listaCodigoProducto.isEmpty())   {
                    Iterator stIterator=listaCodigoProducto.iterator();
                        codigo_producto =(Long)stIterator.next();
                        sipsaDiarioPK.setCodigoProductoSipsaDiario(codigo_producto);
                } 
                else  codigo_producto = new Long (0);
                

        

                List listaCodigoMercado =  entityManager.createNamedQuery(
                        "SipsaMercadosSem.findCodMercadoByNombreMercadoMercadosSem").setParameter("nombreMercadoMercadosSem", sipsaPromedioMayorista.getFuenNombre()).getResultList();
                
                Integer codigo_mercado;
                if (listaCodigoMercado != null && !listaCodigoMercado.isEmpty())   {
                    Iterator stIterator=listaCodigoMercado.iterator();
                    ///////////////// asigna codigo de mercado del diario
                    codigo_mercado =(Integer)stIterator.next();
                    sipsaDiarioPK.setCodigoMercadoSipsaDiario(codigo_mercado);
                } 
                else codigo_mercado = 0;


                ///////////////// obtiene fecha del diario
                Calendar fechaPrecioDiario = sipsaPromedioMayorista.getEnmaFecha().toGregorianCalendar();
                ///////////////// asigna fecha del diario
                sipsaDiarioPK.setFechaSipsaDiario(fechaPrecioDiario.getTime()); 
                ///////////////// nuevo objeto fecha diario igual que el actual
                Calendar fechaPrecioDiarioSemanaAnterior = (Calendar) fechaPrecioDiario.clone();
                ///////////////// quita una semana al objeto copia de fecha diario
                fechaPrecioDiarioSemanaAnterior.add(Calendar.DAY_OF_MONTH, -7);
                ////////////////////////////////////crea objeto de sipsa diario con llave primaria
                SipsaDiario sipsaDiario = new SipsaDiario(sipsaDiarioPK);

                /// si la llave primaria ya existe (osea valor duplicado) persista en tabla con despcripciones
                //  or si los codigo son nulos tambien persista allí 
                if  ( ( entityManager.find(SipsaDiario.class, sipsaDiarioPK) != null) || 
                      ( codigo_producto.intValue() == 0 ) || ( codigo_mercado.intValue() == 0  )  )  {
                    SipsaDiarioConDescripcionesCambios sipsaDiarioConDescripcion = new SipsaDiarioConDescripcionesCambios(codigo_producto, 
                                                                                         codigo_mercado, fechaPrecioDiario.getTime(),codigo_producto);
                     
                    sipsaDiarioConDescripcion.setNombreProductoProductosDiarios(sipsaPromedioMayorista.getArtiNombre());
                sipsaDiarioConDescripcion.setPrecioMaximoDiarioSipsaDiario(sipsaPromedioMayorista.getMaximoKg());
                sipsaDiarioConDescripcion.setPrecioMinimoDiarioSipsaDiario(sipsaPromedioMayorista.getMinimoKg());
                sipsaDiarioConDescripcion.setPrecioPromedioDiarioSipsaDiario(sipsaPromedioMayorista.getPromedioKg());
                sipsaDiarioConDescripcion.setNombreMercado(sipsaPromedioMayorista.getFuenNombre());

            entityManager.persist(sipsaDiarioConDescripcion);
            
                } else {
                    sipsaDiarioPKSemanaAnterior = new SipsaDiarioPK(fechaPrecioDiarioSemanaAnterior.getTime(), codigo_producto, codigo_mercado);              
                    //SipsaDiario sDiarioAnt = new SipsaDiario(sipsaDiarioPKSemanaAnterior);
                    SipsaDiario sipsaDiarioAnterior = entityManager.find(SipsaDiario.class, sipsaDiarioPKSemanaAnterior);
                    ////////////////////////////////////asigna valor acterior, si el valor que habia en la base la semana pasada
                    if (sipsaDiarioAnterior != null) {
                        sipsaDiario.setPrecioSemanaAnt(sipsaDiarioAnterior.getPrecioSemanaAct());   
                    }
                    ////////////////////////////////////asigna valor promedio
                    sipsaDiario.setPrecioSemanaAct(sipsaPromedioMayorista.getPromedioKg().doubleValue());
                    ////////////////////////////////////no hay unidad de medida
                    // sipsaDiario.setUnidadSipsaDiario(  sipsaPromedioMayorista.);
                    sipsaDiario.setPrecioMaximo(sipsaPromedioMayorista.getMaximoKg().doubleValue());
                    sipsaDiario.setPrecioMinimo(sipsaPromedioMayorista.getMinimoKg().doubleValue());
                    
                    entityManager.persist(sipsaDiario);
                }
                trx.commit();
             
            }  
            catch (RuntimeException e) {
                e.printStackTrace();
                continue;
            }
        }   
      entityManager.close();
    }    
        

    private static java.util.List<wsDANE.SipsaPromediosMayoristasParcial> promediosSipsaParcial() {
        wsDANE.SrvSipsaBeanService_Service service = new wsDANE.SrvSipsaBeanService_Service();
        wsDANE.SrvSipsaBeanService port = service.getSrvSipsaBeanServicePort2();
        return port.promediosSipsaParcial();
    }
    //private static wsDANE.

    private static Long getCodigoProducto(EntityManagerImpl entityManager, SipsaPromediosMayoristasParcial spm) {
        /// get codes from names given by DANE's web service
        Long codigo_producto = (Long) entityManager.createNamedQuery(
                "SipsaProductosDiarios.findCodProductoByNombreProductoDiarios").setParameter(
                "nombreProductoProductosDiarios", spm.getArtiNombre()).getSingleResult();
        return codigo_producto;
    }

    private static Integer getCodigoMercado(EntityManagerImpl entityManager, SipsaPromediosMayoristasParcial spm) {
        Integer codigo_mercado = (Integer) entityManager.createNamedQuery(
                "SipsaMercadosSem.findCodMercadoByNombreMercadoMercadosSem").setParameter("nombreMercadoMercadosSem", spm.getFuenNombre()).getSingleResult();
        return codigo_mercado;
    }

    private static Calendar getFechaAnterior(Calendar fecha_sipsa) {
        ///////////////// nuevo objeto fecha diario igual que el actual
        Calendar semana_anterior = (Calendar) fecha_sipsa.clone();
        ///////////////// quita una semana al objeto copia de fecha diario
        semana_anterior.add(Calendar.DAY_OF_MONTH, -7);
        //System.out.print("" + fechaPrecioDiarioSemanaAnterior.getTime());
        return semana_anterior;
    }
}
